//闭包
// 闭包指子函数可以访问外部作用域变量的函数特性，即使在子函数作用域外也可以访问。
// JS中的所有函数都是闭包
// 闭包一般在子函数本身作用域以外执行，即延伸作用域

//【例子1】 使用闭包来封装一个 可复用的数组过滤
let arr = [1,23,4,5,6,7,8,9,234,10,11,12,13,14,15]
//----直接数组过滤，这样虽然可以实现，但是方法不可复用----
let newArr = arr.filter(function(v){
	//保留2~10
	return v >= 2 && v <= 10
})
console.log(newArr)

//----封装一个可复用的方法----
//fn(a,b) 返回一个方法，传入v，判断v是否介于ab之间
let fn = function(a, b){
	return function (v){
		return v >= a && v <= b
	}
}
// console.log(fn(2, 5)(3))//true
// console.log(fn(2, 5)(6))//false
//将新封装的方法，用于数组过滤
let arr2 = arr.filter(fn(2,10))
console.log(arr2)


//【例子2】用闭包封装一个 可复用的排序

let list = [
	{
		name: 'jack',
		age: 36,
		money: 4000
	},
	{
		name: 'tom',
		age: 18,
		money: 2000
	},
	{
		name: 'martin',
		age: 17,
		money: 1000
	},
	{
		name: 'lucy',
		age: 22,
		money: 6000
	}
]
//----排序，这样虽然可以实现，但是方法不可复用----
list.sort((a,b)=>{
	//按年龄排序，升序
	if(a.age > b.age){
		return 1
	}else{
		return -1
	}
})
// console.table(list)

//----封装一个可复用的排序----
//list：数组， item：要排序的对象key， type：默认升序
let listSort = function(list, item, type="asc"){
	return list.sort(function(a, b){
		if(type === "asc"){
			//升序
			return a[item] > b[item] ? 1 : -1
		}else{
			//降序
			return a[item] > b[item] ? -1 : 1
		}
	})
}
//age 降序
console.table(listSort(list, "age", "desc"))
//money 升序
console.table(listSort(list, "money"))

//【总结】
//闭包其实就是一个作用域 以及 内存的问题
//例如：
let a = function a(){
	let n = 1
	console.log(++n)
}
// a();a();a();a(); //此方法无论执行几次，结果都是2

//闭包
let b = function (){
	let n = 1
	//关键在此处，返回了一个function。
	//子函数可以访问外部变量，即使在外部执行也一样。
	//原理：按照js的内存机制，此function被return出来，由b1去接收了，那么这个function就有可能在外部被调用，则js内存会保存此function 以及它外部的变量n。
	return function(){
		console.log(++n)
	}
}
let b1 = b()
b1();b1();b1();// 2, 3, 4
//闭包使用完毕之后 让他指向空，释放内存。
b1 = null
